import axios, { type AxiosInstance, type AxiosRequestConfig } from "axios"
import { useUserStoreHook } from "@/store/modules/user"
import { ElMessage } from "element-plus"
import { get, merge } from "lodash-es"
import { getAccessToken, getRefreshToken } from "./cache/cookies"

/** 退出登录并强制刷新页面（会重定向到登录页） */
function logout() {
  useUserStoreHook().logout()
  location.reload()
}

/** 调整token格式 */
function formatToken(token: any) {
  return `Bearer ${token}`
}

/** 创建请求方法 */
function createRequest(service: AxiosInstance) {
  return function <T>(config: AxiosRequestConfig): Promise<T> {
    const token = getAccessToken()
    const defaultConfig = {
      headers: {
        // 携带 Token
        Authorization: token ? formatToken(token) : undefined,
        "Content-Type": "application/json"
      },
      timeout: 5000,
      baseURL: import.meta.env.VITE_BASE_API,
      data: {}
    }
    // 将默认配置 defaultConfig 和传入的自定义配置 config 进行合并成为 mergeConfig
    const mergeConfig = merge(defaultConfig, config)
    console.log("每次请求处理后的config", mergeConfig)
    return service(mergeConfig)
  }
}

/** 创建请求实例 */
function createService() {
  // 创建一个 axios 实例命名为 service
  const service = axios.create()
  // 请求拦截
  service.interceptors.request.use(
    (config) => config,
    // 发送失败
    (error) => Promise.reject(error)
  )

  //响应拦截这里要加入无痛刷新token部分：
  // 设置一个标志，是否在刷新
  let isRefreshing = false
  // 刷新中其他等待的请求
  let pending: any[] = []
  // 由服务器来区别token是否过期

  // 企业预警通部分
  let isQRefreshing = false
  let qPending: any[] = []
  // 响应拦截（可根据具体业务作出相应的调整）
  service.interceptors.response.use(
    (response) => {
      // apiData 是 api 返回的数据
      const apiData = response.data
      // 二进制数据则直接返回
      const responseType = response.request?.responseType
      if (responseType === "blob" || responseType === "arraybuffer") return apiData
      // 这个 code 是和后端约定的业务 code
      const code = apiData.code
      // 如果没有 code, 代表这不是项目后端开发的 api
      if (code === undefined) {
        ElMessage.error("非本系统的接口")
        return Promise.reject(new Error("非本系统的接口"))
      }
      switch (code) {
        case 200:
          // 本系统采用 code === 200 来表示没有业务错误
          return apiData
        // 对于企业预警通的token过期处理
        // case 401:
        //   // Token 过期时
        //   console.log("企业预警通token过期");
        //   return logout()
        default:
          // 不是正确的 code
          ElMessage.error(apiData.message || "Error")
          return Promise.reject(new Error("Error"))
      }
    },
    async (error) => {
      // status 是 HTTP 状态码
      const status = get(error, "response.status")
      console.log("status", status)
      const { config } = error
      switch (status) {
        case 400:
          error.message = "请求错误"
          break
        case 401:
          // Token 过期时（自己的系统）
          console.log("token过期", error)
          if (!isRefreshing) {
            console.log("刷新token")
            isRefreshing = true
            await useUserStoreHook()._refreshToken()
            const token = getAccessToken()
            config.headers.Authorization = formatToken(token)
            // 已经获取新token了
            pending.forEach((cb) => cb(token))
            // 清空pending
            pending = []
            isRefreshing = false
            return request(config)
          } else {
            // 如果refreshToken也过期，就退出重新登录
            console.log("进入else", config.url)
            if (config.url === "user/refresh_token") {
              console.log("else中的logout")
              logout()
              break
            }
            return new Promise((resolve) => {
              //将resolve放进队列，用一个函数形式来保存，等token刷新后直接执行
              pending.push((token: string) => {
                config.headers.Authorization = formatToken(token)
                resolve(request(config))
              })
            })
          }
        case 4001: // 企业预警通
          console.log("企业预警通token过期", error)
          if (!isQRefreshing) {
            console.log("刷新token")
            isQRefreshing = true

            // await useUserStoreHook()._refreshToken()
            // const token = getAccessToken()
            // config.headers.Authorization = formatToken(token)
            // 已经获取新token了
            // pending.forEach((cb) => cb(token))
            // 清空pending
            qPending = []
            isQRefreshing = false
            return request(config)
          } else {
            // 如果refreshToken也过期，就退出重新登录
            console.log("进入else", config.url)
            if (config.url === "user/refresh_token") {
              console.log("else中的logout")
              // logout()
              break
            }
            return new Promise((resolve) => {
              //将resolve放进队列，用一个函数形式来保存，等token刷新后直接执行
              qPending.push((token: string) => {
                config.headers.Authorization = formatToken(token)
                resolve(request(config))
              })
            })
          }
        // error.message = "企业预警通token过期"
        // break
        case 403:
          error.message = "拒绝访问"
          break
        case 404:
          error.message = "请求地址出错"
          break
        case 408:
          error.message = "请求超时"
          break
        case 500:
          error.message = "服务器内部错误"
          break
        case 501:
          error.message = "服务未实现"
          break
        case 502:
          error.message = "网关错误"
          break
        case 503:
          error.message = "服务不可用"
          break
        case 504:
          error.message = "网关超时"
          break
        case 505:
          error.message = "HTTP 版本不受支持"
          break
        default:
          break
      }
      ElMessage.error(error.message)
      return Promise.reject(error)
    }
  )
  return service
}

/** 用于网络请求的实例 */
const service = createService()
/** 用于网络请求的方法 */
export const request = createRequest(service)
